package com.winning.pmph.utils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.ParseSettings;
import org.jsoup.parser.Parser;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 刘亚飞
 * @Description
 * @create 2021-03-30 16:26
 */
@Slf4j
public class ParseBookZipUtil {

    public static String unzipBook(String bookPath, String header) {
        // 先删除原解压文件;
        String unzipPath = StringUtils.removeEnd(bookPath, ".zip");
        try {
            FileUtils.deleteQuietly(new File(unzipPath));
            ZipUtil.unZip(bookPath, header);
        } catch (Exception e) {
            log.error("解压zip包失败：", e);
            throw new RuntimeException("解压zip包失败：" + e.toString());
        }
        return unzipPath;
    }

    /**
     * 递归查询文件,
     *
     * @param dir 父文件夹
     */
    public static String recursiveFindFile(File dir, List<String> fileList) {
        if (isFound(dir, fileList)) {
            return dir.getAbsolutePath();
        }
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                String path = recursiveFindFile(file, fileList);
                if (StringUtils.isNotBlank(path)) {
                    return path;
                }
            }
        }
        return "";
    }

    private static boolean isFound(File dir, List<String> fileList) {
        String subFileNames = StringUtils.join(dir.list(), ",");
        for (String fileName : fileList) {
            if (!subFileNames.contains(fileName)) {
                return false;
            }
        }
        return true;
    }

    public static String parseBookMetadata(String analysisPath) {
        // 解析元数据
        LinkedHashMap metadataMap = parseMetadataXml2Json(analysisPath, "meta.xml", "book_metadata");
        // 判断图书是否有封面图;
        String coverImg = Arrays.stream(new File(analysisPath).listFiles())
                .map(File::getName)
                .filter(fileName -> fileName.endsWith(".jpg")
                        || fileName.endsWith("jpeg")
                        || fileName.endsWith("png")
                        || fileName.endsWith("bmp"))
                .collect(Collectors.joining(","));
        metadataMap.put("coverImg", coverImg);
        return JSON.toJSONString(metadataMap);
    }

    public static String parseFrontBook(String analysisPath) {
        // 解析文前
        LinkedHashMap frontMap = parseMetadataXml2Json(analysisPath, "front.xml", "front_of_book");
        return JSON.toJSONString(frontMap);
    }

    private static LinkedHashMap parseMetadataXml2Json(String analysisPath, String xmlName, String tagName) {
        try {
            File metadataFile = new File(analysisPath + "/" + xmlName);
            String metadataStr = FileUtils.readFileToString(metadataFile);
            Parser parser = Parser.xmlParser().settings(new ParseSettings(true, true));
            Document metadataDocument = Jsoup.parse(metadataStr, metadataFile.getPath(), parser);
            Element metadataElement = metadataDocument.getElementsByTag(tagName).first();
            return parseMetadataXml2JsonWithOrder(metadataElement, new LinkedHashMap());
        } catch (Exception e) {
            log.error("解析" + xmlName + "时发生错误：", e);
            throw new RuntimeException("解析" + xmlName + "时发生错误：" + e.toString());
        }
    }

    private static LinkedHashMap parseMetadataXml2JsonWithOrder(Element element, LinkedHashMap map) {
        for (Element child : element.children()) {
            if (child.children().size() > 0) {
                LinkedHashMap<String, LinkedHashMap> subMap = parseMetadataXml2JsonWithOrder(child, new LinkedHashMap());
                Object priSibling = map.get(child.tagName());
                if (Objects.isNull(priSibling)) {
                    if (Objects.equals("Creator", child.tagName()) || Objects.equals("Contributor", child.tagName())) {
                        ArrayList<LinkedHashMap> list = new ArrayList<>();
                        list.add(subMap);
                        map.put(child.tagName(), list);
                    } else {
                        map.put(child.tagName(), subMap);
                    }
                } else if (priSibling instanceof List) {
                    ((List) priSibling).add(subMap);
                } else {
                    List<Object> value = new ArrayList();
                    value.add(priSibling);
                    value.add(subMap);
                    map.put(child.tagName(), value);
                }
            } else {
                if (Objects.equals("Creators", child.tagName())) {
                    ArrayList<LinkedHashMap> list = new ArrayList<>();
                    Map<String, List<LinkedHashMap>> tmp = Maps.newLinkedHashMap();
                    tmp.put("Creator", list);
                    map.put("Creators", tmp);
                } else if (Objects.equals("Contributors", child.tagName())) {
                    ArrayList<LinkedHashMap> list = new ArrayList<>();
                    Map<String, List<LinkedHashMap>> tmp = Maps.newLinkedHashMap();
                    tmp.put("Contributor", list);
                    map.put("Contributors", tmp);
                } else {
                    map.put(child.tagName(), child.text());
                }
            }
        }
        return map;
    }

    public static String copyPicAndTable(String xmlPath, String picsPath) {
        try {
            // 把图书里的图片统一存储到这个路径下
            String targetDirPath = ApplicationContextUtil.BASE_DOWN_FORDER + picsPath;
            FileUtils.deleteDirectory(new File(targetDirPath));
            FileUtils.copyDirectory(new File(xmlPath), new File(targetDirPath));
            return targetDirPath + "/pics";
        } catch (Exception e) {
            log.error("移动图片文件夹异常：", e);
            throw new RuntimeException("移动图片文件夹异常：" + e.toString());
        }
    }
}
